<?php
declare(strict_types=1);

namespace Service\CommodityService;

use Service\BaseService;
use Service\Code\Normal;
use App\Model\BbcModel\Goods;
use App\Model\BbcModel\GoodsClass;
use App\Model\BbcModel\GoodsManagerTags;
use App\Model\BbcModel\Storage;
use App\Model\BbcModel\ConfigChannel;
use App\Model\BbcModel\GoodsBrand;
use App\Model\BbcModel\Goodscommon;
use App\Model\BbcModel\GoodsSupplyClass;
use App\Model\BbcModel\GoodsService;
use App\Model\BbcModel\TransitTemplate;
use App\Model\BbcModel\GoodsSpecPrice;
use App\Model\BbcModel\GoodsBatch;
use App\Model\BbcModel\DistributorPrice;
use App\Model\BbcModel\DistributorLevel;
use App\Model\BbcModel\Country;
use App\Model\BbcModel\Mnuser;
use App\Model\BbcModel\MnStoreGoods;
use App\Model\BbcModel\CashGoodsChange;
use App\Model\BbcModel\GoodsLog;
use App\Model\BbcModel\GoodsAttach;
use Hyperf\DbConnection\Db;
use Service\ExportService\ExportExcelHandle;

/**
 * 渠道商品服务-代发商品
 * @author chenshubo
 */
class ChannelCommodityService extends BaseService {
    /**
     * 代发商品列表
     * @param array $param
     */
    public function goodsList(array $param) {
        $param['sp'] = 0;
        if (isset($param['page']) && ctype_digit((string)$param['page']) && $param['page'] > 0) {
            $this->page = $param['page'];
        }
        if (isset($param['limit']) && ctype_digit((string)$param['limit']) && $param['limit'] > 0) {
            $this->limit = $param['limit'];
        }
        $whereRaw = ChannelCommodityCommonService::instance()->handleWhere($param);
        $sortRaw  = ChannelCommodityCommonService::instance()->handleSort($param);
        $fields   = [
            'id', 'img', 'name', 'barcode', 'skucode', 'class_id', 'brand_id', 'num_sale', 'month_sale', 'is_high_goods', 'high_tax_rate',
            'stoid', 'tax_free', 'high_price', 'tax_rate', 'is_update', 'status', 'price_store', 'manager_tag', 'num_storage', 'warn_storage',
            'is_bonded', 'is_trade', 'price_cost', 'price_market', 'show_order', 'up', 'price_recommend', 'price_recommend_vip', 'cd', 'medicinal',
            'isfree_postfee', 'supplier_name', 'weight', 'origin', 'supply_class_id', 'service_id', 'template_id', 'buy_limit', 'type', 'is_price_cost_change'
        ];
        $result   = Goods::select($fields)->where('is_trade', 0)->whereRaw($whereRaw)->orderByRaw($sortRaw)->paginate($this->limit, ['*'], 'page', $this->page);
        if ($result->isEmpty()) {
            return Normal::returnCode(Normal::SUC, '获取成功', [
                'onLineCount'  => 0,//已上架商品数
                'offLineCount' => 0,//已下架商品数
                'allCount'     => 0,//总商品数
                'newCount'     => 0,//新品待上架商品数
                'riskCount'    => 0,//风控下架商品数
                'manualCount'  => 0,//手动下架商品数
                'list'         => [],
                'total'        => 0,
            ]);
        }
        $collection = $result->getCollection();
        $goods_ids  = $collection->pluck('id')->toArray();
        $goodsSpec  = GoodsSpecPrice::whereIn('goods_id', $goods_ids)->get()->toArray();
        $specBygid  = [];
        if ($goodsSpec) {
            foreach ($goodsSpec as $spec) {
                $specBygid[$spec['goods_id']][] = $spec;
            }
        }
        $tagArr     = GoodsManagerTags::where('cid', $param['cid'])->where('df', 0)->pluck('name', 'id')->toArray();
        $storageArr = Storage::where('cid', 0)->where('df', 0)->pluck('desc', 'id')->toArray();
        $payRate    = ConfigChannel::instance()->getPayFee(['cid' => $param['cid']]);
        $class_ids  = $collection->pluck('class_id')->toArray();
        $allClass   = GoodsClass::whereIn('id', $class_ids)->pluck('name', 'id')->toArray();
        $brand_ids  = $collection->pluck('brand_id')->toArray();
        $allBrand   = GoodsBrand::whereIn('id', $brand_ids)->pluck('name', 'id')->toArray();
        $sclass_ids = $collection->pluck('supply_class_id')->toArray();
        $sclassArr  = GoodsSupplyClass::whereIn('id', $sclass_ids)->pluck('name', 'id')->toArray();
        $serviceArr = GoodsService::where('cid', $param['cid'])->where('status', 1)->pluck('title', 'id')->toArray();
        $tplArr     = TransitTemplate::where('cid', $param['cid'])->where('df', 0)->pluck('name', 'id')->toArray();
        $collection->each(function ($item, $key) use ($tagArr, $storageArr, $payRate, $allClass, $allBrand, $sclassArr, $serviceArr, $tplArr, $specBygid) {
            $specArr = $specBygid[$item->id] ?? [];
            $newSpec = [];
            foreach ($specArr as $spec) {
                $costUnitPrice            = bcdiv((string)($spec['price_cost']), (string)($spec['spec_num']), 2);//成本单价
                $settlementUnitPrice      = bcdiv((string)($spec['price_store']), (string)($spec['spec_num']), 2);//结算单价
                $costUnitPricNoTax        = $costUnitPrice;//不含税成本单价
                $settlementUnitPriceNoTax = $settlementUnitPrice;//不含税结算单价
                if ($item->is_bonded == 1 && $item->tax_free == 1) {
                    if ($item->high_price > 0) {
                        $pricestoretax_rate = $item->tax_rate;
                        $pricecosttax_rate  = $item->tax_rate;
                        if ($settlementUnitPrice >= $item->high_price) {
                            $pricestoretax_rate = $item->high_tax_rate;
                        }
                        if ($costUnitPrice >= $item->high_price) {
                            $pricecosttax_rate = $item->high_tax_rate;
                        }
                        $settlementUnitPriceNoTax = round(($settlementUnitPrice / (1 + $pricestoretax_rate)), 2);
                        $costUnitPricNoTax        = round($costUnitPrice / (1 + $pricecosttax_rate), 2);
                    } else {
                        $settlementUnitPriceNoTax = round($settlementUnitPrice / (1 + $item->tax_rate), 2);
                        $costUnitPricNoTax        = round($costUnitPrice / (1 + $item->tax_rate), 2);
                    }
                }
                $unitProfit      = bcsub((string)$settlementUnitPriceNoTax, (string)$costUnitPricNoTax, 2);
                $unitProfitTotal = bcmul($unitProfit, (string)($spec['spec_num']), 2);
                $newSpec[]       = [
                    'spec_num'               => $spec['spec_num'],
                    'price_market'           => $spec['price_market'],
                    'price_recommend'        => $spec['price_recommend'],
                    'price_recommend_vip'    => $spec['price_recommend_vip'],
                    'high_price'             => bcmul((string)($spec['spec_num']), (string)($item->high_price), 2),//含税预警价
                    'cost_price_total'       => $costUnitPrice . '/' . $spec['price_cost'],
                    'settlement_price_total' => $settlementUnitPrice . '/' . $spec['price_store'],
                    'unit_profit_total'      => round($unitProfit * $payRate, 2) . '/' . round($unitProfitTotal * $payRate, 2),//单件利润小计算
                ];
            }
            $item->goods_spec      = $newSpec;
            $item->settlement_type = Goods::$settlementType[$item->type] ?? '';
            $item->class_text      = $allClass[$item->class_id] ?? '';
            $item->brand_text      = $allBrand[$item->brand_id] ?? '';
            $item->template        = $tplArr[$item->template_id] ?? '';
            $item->status_text     = Goods::$status[$item->status] ?? '';
            $item->has_storage     = $item->num_storage > 0 ? '是' : '否';
            $item->storage_name    = $storageArr[$item->stoid] ?? '';
            $item->has_price       = $item->price_store > 0 ? '是' : '否';
            $item->is_high         = $item->is_high_goods > 0 ? '已触发消费税' : '';
            $item->is_price_wrong  = "否";
            if ($item->price_recommend_vip > $item->price_recommend || $item->price_recommend < $item->price_store || $item->price_recommend_vip < $item->price_store || $item->price_cost > $item->price_store) {
                $item->is_price_wrong = "是";
            }
            if (!empty($item->manager_tag)) {
                $tag    = explode(',', $item->manager_tag);
                $tagStr = '';
                foreach ($tag as $v) {
                    if (isset($tagArr[$v])) {
                        $tagStr .= $tagArr[$v] . ',';
                    }
                }
                if (!empty($tagStr)) {
                    $item->manager_tag = rtrim($tagStr, ',');
                } else {
                    $item->manager_tag = '';
                }
            }
            $item->cd = date('Y-m-d H:i:s', $item->cd);
            //预估利润
            if ($item->is_bonded == 1 && $item->tax_free == 1) {
                if ($item->high_price > 0) {
                    $pricestoretax_rate = $item->tax_rate;
                    $pricecosttax_rate  = $item->tax_rate;
                    if ($item->price_store >= $item->high_price) {
                        $pricestoretax_rate = $item->high_tax_rate;
                    }
                    if ($item->price_cost >= $item->high_price) {
                        $pricecosttax_rate = $item->high_tax_rate;
                    }
                    $item->except_money = round(($item->price_store / (1 + $pricestoretax_rate) - $item->price_cost / (1 + $pricecosttax_rate)) * $payRate, 2);
                } else {
                    $item->except_money = round(($item->price_store / (1 + $item->tax_rate) - $item->price_cost / (1 + $item->tax_rate)) * $payRate, 2);
                }
            } else {
                $item->except_money = round(($item->price_store - $item->price_cost) * $payRate, 2);
            }
            $item->is_bonded         = Goodscommon::$is_bonded[$item['is_bonded']] ?? '';
            $item->weight            = $item->weight . '克';
            $item->supply_class_text = $sclassArr[$item->supply_class_id] ?? '';
            //$serviceArr   service_id
            $item->service_text = '';
            if (!empty($item->service_id)) {
                $service_ids    = explode(',', $item->service_id);
                $serviceTextArr = [];
                foreach ($service_ids as $serid) {
                    if (isset($serviceArr[$serid])) {
                        array_push($serviceTextArr, $serviceArr[$serid]);
                    }
                }
                $item->service_text = $serviceTextArr ? implode(',', $serviceTextArr) : '';
            }
            return $item;
        });
        //设置商品数目
        $goodsCountFields = ['id', 'status', 'down_status'];
        $goodsQueryCount  = Goods::where('df', 0)->where('cid', $param['cid'])->where('is_trade', 0)->whereIn('is_fast_delivery', [0, 2])->select($goodsCountFields)->get()->toArray();
        $onLineCount      = 0;
        $offLineCount     = 0;
        $allCount         = 0;
        $newCount         = 0;
        $riskCount        = 0;
        $manualCount      = 0;
        foreach ($goodsQueryCount as $v) {
            if ($v['status'] == 1) {
                $onLineCount += 1;
            }
            if ($v['status'] == 0) {
                $offLineCount += 1;
            }
            if ($v['status'] == 0 && $v['down_status'] == 1) {
                $newCount += 1;
            }
            if ($v['status'] == 0 && $v['down_status'] == 2) {
                $riskCount += 1;
            }
            if ($v['status'] == 0 && $v['down_status'] == 0) {
                $manualCount += 1;
            }
        }
        $allCount = $onLineCount + $offLineCount;
        $data     = [
            'onLineCount'  => $onLineCount,//已上架商品数
            'offLineCount' => $offLineCount,//已下架商品数
            'allCount'     => $allCount,//总商品数
            'newCount'     => $newCount,//新品待上架商品数
            'riskCount'    => $riskCount,//风控下架商品数
            'manualCount'  => $manualCount,//手动下架商品数
            'list'         => $collection->toArray(),
            'total'        => $result->total(),
        ];
        return Normal::returnCode(Normal::SUC, "获取成功", $data);
    }

    /**
     * 标签列表
     * @param array $param
     */
    public function tagList(array $param) {
        if (!isset($param['cid']) || empty($param['cid']) || (preg_match("/^[1-9]\d*$/", (string)$param['cid']) != 1)) {
            return Normal::returnCode(Normal::FAIL, 'invalid argument cid');
        }
        $param['cid'] = (int)($param['cid']);
        $result       = GoodsManagerTags::where('cid', $param['cid'])->where('df', 0)->select('name', 'id')->get()->toArray();
        return Normal::returnCode(Normal::SUC, "获取成功", $result);
    }

    /**
     * 批量设置标签
     * @param array $param
     */
    public function setTag(array $param) {
        if (!isset($param['cid']) || empty($param['cid']) || (preg_match("/^[1-9]\d*$/", (string)$param['cid']) != 1)) {
            return Normal::returnCode(Normal::FAIL, 'invalid argument cid');
        }
        if (!isset($param['tag_ids']) || empty($param['tag_ids']) || !is_array($param['tag_ids'])) {
            return Normal::returnCode(Normal::FAIL, 'invalid argument tag_ids');
        }
        if (!isset($param['goods_ids']) || empty($param['goods_ids']) || !is_array($param['goods_ids'])) {
            return Normal::returnCode(Normal::FAIL, 'invalid argument goods_ids');
        }
        $param['cid'] = (int)($param['cid']);
        $isTrade      = $param['is_trade'] ?? 0;
        $tagStr       = implode(',', $param['tag_ids']);
        Goods::whereIn('id', $param['goods_ids'])->where('cid', $param['cid'])->where('is_fast_delivery', '<>', 1)->where('is_trade', $isTrade)->update(['manager_tag' => $tagStr, 'md' => time()]);
        return Normal::returnCode(Normal::SUC, '设置成功');
    }

    /**
     * 批量设置商品服务
     * @param array $param
     */
    public function setService(array $param) {
        if (!isset($param['cid']) || empty($param['cid']) || (preg_match("/^[1-9]\d*$/", (string)$param['cid']) != 1)) {
            return Normal::returnCode(Normal::FAIL, 'invalid argument cid');
        }
        if (!isset($param['service_ids']) || empty($param['service_ids']) || !is_array($param['service_ids'])) {
            return Normal::returnCode(Normal::FAIL, 'invalid argument service_ids');
        }
        if (!isset($param['goods_ids']) || empty($param['goods_ids']) || !is_array($param['goods_ids'])) {
            return Normal::returnCode(Normal::FAIL, 'invalid argument goods_ids');
        }
        $param['cid'] = (int)($param['cid']);
        $isTrade      = $param['is_trade'] ?? 0;
        $serviceStr   = implode(',', $param['service_ids']);
        Goods::whereIn('id', $param['goods_ids'])->where('cid', $param['cid'])->where('is_fast_delivery', '<>', 1)->where('is_trade', $isTrade)->update(['service_id' => $serviceStr, 'md' => time()]);
        return Normal::returnCode(Normal::SUC, '设置成功');
    }

    /**
     * 批量设置运费模板
     * @param array $param
     */
    public function setExpressTpl(array $param) {
        if (!isset($param['cid']) || empty($param['cid']) || (preg_match("/^[1-9]\d*$/", (string)$param['cid']) != 1)) {
            return Normal::returnCode(Normal::FAIL, 'invalid argument cid');
        }
        if (!isset($param['template_id']) || empty($param['template_id'])) {
            return Normal::returnCode(Normal::FAIL, 'invalid argument template_id');
        }
        if (!isset($param['goods_ids']) || empty($param['goods_ids']) || !is_array($param['goods_ids'])) {
            return Normal::returnCode(Normal::FAIL, 'invalid argument goods_ids');
        }
        $param['cid'] = (int)($param['cid']);
        $tplId        = (int)($param['template_id']);
        $tpl          = TransitTemplate::where('id', $tplId)->where('cid', $param['cid'])->where('df', 0)->exists();
        if (empty($tpl)) {
            return Normal::returnCode(Normal::FAIL, "运费模板不存在");
        }
        $isTrade = $param['is_trade'] ?? 0;
        Goods::whereIn('id', $param['goods_ids'])->where('cid', $param['cid'])->where('is_fast_delivery', '<>', 1)->where('is_trade', $isTrade)->update(['template_id' => $tplId, 'md' => time()]);
        return Normal::returnCode(Normal::SUC, '设置成功');
    }

    /**
     * 批量设置限购数量
     * @param array $param
     */
    public function setBuyLimit(array $param) {
        if (!isset($param['cid']) || empty($param['cid']) || (preg_match("/^[1-9]\d*$/", (string)$param['cid']) != 1)) {
            return Normal::returnCode(Normal::FAIL, 'invalid argument cid');
        }
        if (!isset($param['limit_num']) || empty($param['limit_num']) || (preg_match("/^[1-9]\d*$/", (string)$param['limit_num']) != 1)) {
            return Normal::returnCode(Normal::FAIL, 'invalid argument limit_num');
        }
        if (!isset($param['goods_ids']) || empty($param['goods_ids']) || !is_array($param['goods_ids'])) {
            return Normal::returnCode(Normal::FAIL, 'invalid argument goods_ids');
        }
        $param['cid'] = (int)($param['cid']);
        $isTrade      = $param['is_trade'] ?? 0;
        $data         = ['buy_limit' => (int)($param['limit_num']), 'limit_type' => 1, 'md' => time()];
        Goods::whereIn('id', $param['goods_ids'])->where('cid', $param['cid'])->where('is_fast_delivery', '<>', 1)->where('is_trade', $isTrade)->where('limit_type', '<>', 2)->update($data);
        return Normal::returnCode(Normal::SUC, '设置成功');
    }

    /**
     * 批量设置商品分类
     * @param array $param
     */
    public function setGoodsClass(array $param) {
        if (!isset($param['cid']) || empty($param['cid']) || (preg_match("/^[1-9]\d*$/", (string)$param['cid']) != 1)) {
            return Normal::returnCode(Normal::FAIL, 'invalid argument cid');
        }
        if (!isset($param['class_id']) || empty($param['class_id']) || (preg_match("/^[1-9]\d*$/", (string)$param['class_id']) != 1)) {
            return Normal::returnCode(Normal::FAIL, 'invalid argument class_id');
        }
        if (!isset($param['goods_ids']) || empty($param['goods_ids']) || !is_array($param['goods_ids'])) {
            return Normal::returnCode(Normal::FAIL, 'invalid argument goods_ids');
        }
        $param['cid'] = (int)($param['cid']);
        $isTrade      = $param['is_trade'] ?? 0;
        $data         = ['class_id' => (int)($param['class_id']), 'md' => time()];
        Goods::whereIn('id', $param['goods_ids'])->where('cid', $param['cid'])->where('is_fast_delivery', '<>', 1)->where('is_trade', $isTrade)->update($data);
        //更新ES索引
        ChannelCommodityEsService::instance()->updateIndexByClassId($param['class_id'], $param['cid']);
        return Normal::returnCode(Normal::SUC, '设置成功');
    }

    /**
     * 批量设置预警库存
     * @param array $param
     */
    public function setWarnStorage(array $param) {
        if (!isset($param['cid']) || empty($param['cid']) || (preg_match("/^[1-9]\d*$/", (string)$param['cid']) != 1)) {
            return Normal::returnCode(Normal::FAIL, 'invalid argument cid');
        }
        if (!isset($param['warn_storage_num']) || empty($param['warn_storage_num']) || (preg_match("/^[1-9]\d*$/", (string)$param['warn_storage_num']) != 1)) {
            return Normal::returnCode(Normal::FAIL, 'invalid argument warn_storage_num');
        }
        if (!isset($param['goods_ids']) || empty($param['goods_ids']) || !is_array($param['goods_ids'])) {
            return Normal::returnCode(Normal::FAIL, 'invalid argument goods_ids');
        }
        $param['cid'] = (int)($param['cid']);
        $isTrade      = $param['is_trade'] ?? 0;
        $data         = ['warn_storage' => (int)($param['warn_storage_num']), 'md' => time()];
        Goods::whereIn('id', $param['goods_ids'])->where('cid', $param['cid'])->where('is_fast_delivery', '<>', 1)->where('is_trade', $isTrade)->update($data);
        return Normal::returnCode(Normal::SUC, '设置成功');
    }

    /**
     * 批量设置上下架
     * @param array $param
     */
    public function setOnlineStatus(array $param) {
        if (!isset($param['cid']) || empty($param['cid']) || (preg_match("/^[1-9]\d*$/", (string)$param['cid']) != 1)) {
            return Normal::returnCode(Normal::FAIL, 'invalid argument cid');
        }
        if (!isset($param['status']) || !in_array($param['status'], ['1', '0'])) {
            return Normal::returnCode(Normal::FAIL, 'invalid argument status');
        }
        if (!isset($param['goods_ids']) || empty($param['goods_ids']) || !is_array($param['goods_ids'])) {
            return Normal::returnCode(Normal::FAIL, 'invalid argument goods_ids');
        }
        $param['cid'] = (int)($param['cid']);
        $isTrade      = $param['is_trade'] ?? 0;
        $data         = ['status' => $param['status'], 'md' => time()];
        if ($param['status'] == 0) {
            $data['down_status'] = 0;
        }
        $model = Goods::whereIn('id', $param['goods_ids'])->where('cid', $param['cid'])->where('is_fast_delivery', '<>', 1)->where('is_trade', $isTrade);
        if ($param['status'] == 1 && $isTrade == 0) {
            $model = $model->whereRaw(" num_storage>0 and price_cost <= price_store and price_recommend>=price_store and price_recommend_vip>=price_store");
        }
        $model->update($data);
        //ES更新索引
        ChannelCommodityEsService::instance()->updateIndexByOnlineStatus($param);
        return Normal::returnCode(Normal::SUC, '设置成功');
    }

    /**
     * 代发商品详情
     * @param array $param
     */
    public function goodsInfo(array $param) {
        if (!isset($param['cid']) || empty($param['cid']) || (preg_match("/^[1-9]\d*$/", (string)$param['cid']) != 1)) {
            return Normal::returnCode(Normal::FAIL, 'invalid argument cid');
        }
        if (!isset($param['goods_id']) || empty($param['goods_id']) || (preg_match("/^[1-9]\d*$/", (string)$param['goods_id']) != 1)) {
            return Normal::returnCode(Normal::FAIL, 'invalid argument goods_id');
        }
        $fields = [
            'id', 'name', 'skucode', 'barcode', 'price_cost', 'price_store', 'is_trade', 'tax_rate', 'high_tax_rate', 'high_price',
            'price_market', 'license_no', 'price_vip', 'service_id', 'price_recommend', 'num_storage', 'class_id', 'origin', 'weight', 'brand_id', 'img',
            'body', 'is_bonded', 'status', 'price_recommend_vip', 'cd', 'medicinal', 'is_update', 'profit_price', 'profit',
            'profit_vip', 'type', 'template_id', 'buy_limit', 'express_template', 'isfree_postfee', 'tag', 'supply_tag', 'tax_free_cloud', 'origin_id',
            'manager_tag', 'warn_storage', 'tax_free', 'show_order'
        ];
        $info   = Goods::select($fields)->where('id', $param['goods_id'])->where('cid', $param['cid'])->first();
        if (empty($info)) {
            return Normal::returnCode(Normal::FAIL, "指定商品信息不存在");
        }
        $info               = $info->toArray();
        $info['service_id'] = $info['service_id'] ? explode(',', $info['service_id']) : [];
        if ($info['service_id']) {
            $info['service_id'] = array_map(function ($v11) {
                return (int)$v11;
            }, $info['service_id']);
        }
        $info['tag'] = $info['tag'] ? explode(',', $info['tag']) : [];
        if ($info['tag']) {
            $info['tag'] = array_map(function ($v22) {
                return (int)$v22;
            }, $info['tag']);
        }
        $info['supply_tag'] = $info['supply_tag'] ? explode(',', $info['supply_tag']) : [];
        if ($info['supply_tag']) {
            $info['supply_tag'] = array_map(function ($v33) {
                return (int)$v33;
            }, $info['supply_tag']);
        }
        $info['manager_tag'] = $info['manager_tag'] ? explode(',', $info['manager_tag']) : [];
        if ($info['manager_tag']) {
            $info['manager_tag'] = array_map(function ($v44) {
                return (int)$v44;
            }, $info['manager_tag']);
        }
        $info['weight_kg']       = round($info['weight'] / 1000, 3);
        $info['settlement_type'] = Goods::$settlementType[$info['type']] ?? '固定价格';
        $info['goods_type']      = Goodscommon::$is_bonded[$info['is_bonded']] ?? '';
        $attach                  = GoodsAttach::where('common_id', $info['id'])->where('type', 1)->where('df', 0)->orderBy('id', 'desc')->pluck('url')->toArray();
        if ($info['img']) {
            array_unshift($attach, $info['img']);
        }
        $info['img'] = $attach;
        if ($info['buy_limit'] == 0 && $info['is_bonded'] == 1) {
            $info['buy_limit'] = 6;
        }
        if ($info['buy_limit'] == 0) {
            $info['buy_limit'] = '无';
        }
        if ($info['is_bonded'] == 1) {
            //成本不含税价格
            if ($info['price_cost'] >= $info['high_price'] && $info['high_price'] > 0) {
                $info['price_cost_r'] = round($info['price_cost'] / (1 + $info['high_tax_rate']), 2);
            } else {
                $info['price_cost_r'] = round($info['price_cost'] / (1 + $info['tax_rate']), 2);
            }
        }
        $distributorLevel      = DistributorLevel::where('cid', $param['cid'])->select(['level', 'name'])->get()->toArray();
        $hasBatch              = GoodsBatch::where('goods_id', $param['goods_id'])->where('type', 0)->first();
        $hasBatch              = empty($hasBatch) ? [] : $hasBatch->toArray();
        $specList              = isset($hasBatch['spec_list']) && !empty($hasBatch['spec_list']) ? json_decode($hasBatch['spec_list'], true) : [['spec_num' => 1]];
        $specPriceFields       = ['price_recommend_vip', 'price_recommend', 'price_cost', 'price_store', 'price_market', 'spec_num'];
        $specListPriceAll      = GoodsSpecPrice::where('goods_id', $param['goods_id'])->select($specPriceFields)->get()->toArray();
        $specListPriceAll      = array_column($specListPriceAll, null, 'spec_num');
        $distributorPrice      = DistributorPrice::where('goods_id', $param['goods_id'])->select(['level_id', 'spec_num', 'goods_id', 'price'])->get()->toArray();
        $payRate               = ConfigChannel::instance()->getPayFee(['cid' => $param['cid']]);
        $distributorLevelPrice = [];
        foreach ($specList as $key => $val) {
            $specListPrice                         = $specListPriceAll[$val['spec_num']] ?? [];
            $specList[$key]['price_recommend_vip'] = $specListPrice['price_recommend_vip'] ?? '0.00';
            $specList[$key]['price_recommend']     = $specListPrice['price_recommend'] ?? '0.00';
            $specList[$key]['price_store']         = $specListPrice['price_store'] ?? '0.00';
            $specList[$key]['price_cost']          = $specListPrice['price_cost'] ?? '0.00';
            $specList[$key]['price_market']        = $specListPrice['price_market'] ?? '0.00';
            $specList[$key]['high_price']          = bcmul((string)($val['spec_num']), (string)($info['high_price']), 2);//含税预警价
            $costPrice                             = $specList[$key]['price_cost'];
            $settlementPrice                       = $specList[$key]['price_store'];
            if ($info['is_bonded'] == 1 && $info['tax_free'] == 1) {
                if ($info['high_price'] > 0) {
                    $pricestoretax_rate = $info['tax_rate'];
                    $pricecosttax_rate  = $info['tax_rate'];
                    if ($settlementPrice >= $info['high_price']) {
                        $pricestoretax_rate = $info['high_tax_rate'];
                    }
                    if ($costPrice >= $info['high_price']) {
                        $pricecosttax_rate = $info['high_tax_rate'];
                    }
                    $except_money = round(($settlementPrice / (1 + $pricestoretax_rate) - $costPrice / (1 + $pricecosttax_rate)) * $payRate, 2);
                } else {
                    $except_money = round(($settlementPrice / (1 + $info['tax_rate']) - $costPrice / (1 + $info['tax_rate'])) * $payRate, 2);
                }
            } else {
                $except_money = round(($settlementPrice - $costPrice) * $payRate, 2);
            }
            $specList[$key]['except_money'] = $except_money;
            foreach ($distributorLevel as $k => $v) {
                $specList[$key]['distributor_level'][$k]['name']  = $v['name'];
                $specList[$key]['distributor_level'][$k]['level'] = $v['level'];
                $price                                            = 0;
                foreach ($distributorPrice as $item) {
                    if ($item['level_id'] == $v['level'] && $item['spec_num'] == $val['spec_num']) {
                        $price = $item['price'];
                    }
                }
                if ($price) {
                    $specList[$key]['distributor_level'][$k]['price'] = $price;
                } else {
                    $specList[$key]['distributor_level'][$k]['price'] = '0.00';
                }
            }
        }
        $info['spec_list'] = $specList;
        return Normal::returnCode(Normal::SUC, '获取成功', $info);
    }

    /**
     * 代发商品编辑
     * @param array $param
     */
    public function goodsEdit(array $param) {
        if (!isset($param['cid']) || empty($param['cid']) || (preg_match("/^[1-9]\d*$/", (string)$param['cid']) != 1)) {
            return Normal::returnCode(Normal::FAIL, 'invalid argument cid');
        }
        if (!isset($param['goods_id']) || empty($param['goods_id']) || (preg_match("/^[1-9]\d*$/", (string)$param['goods_id']) != 1)) {
            return Normal::returnCode(Normal::FAIL, 'invalid argument goods_id');
        }
        $goods = Goods::where('id', $param['goods_id'])->where('cid', $param['cid'])->first();
        if (empty($goods)) {
            return Normal::returnCode(Normal::FAIL, "指定商品信息不存在");
        }
        $goods = $goods->toArray();
        if (!isset($param['name']) || empty($param['name'])) {
            return Normal::returnCode(Normal::FAIL, 'invalid argument name');
        }
        if (isset($param['origin_id']) && $goods['origin_id'] != $param['origin_id']) {
            if (empty($param['origin_id']) || (preg_match("/^[1-9]\d*$/", (string)$param['origin_id']) != 1)) {
                return Normal::returnCode(Normal::FAIL, 'invalid argument origin_id');
            }
        }
        if (isset($param['buy_limit']) && $goods['buy_limit'] != $param['buy_limit']) {
            if (empty($param['buy_limit']) || (preg_match("/^[1-9]\d*$/", (string)$param['buy_limit']) != 1)) {
                return Normal::returnCode(Normal::FAIL, 'invalid argument buy_limit');
            }
            if ($goods['is_trade'] == 0) {
                if (($param['buy_limit'] != $goods['buy_limit']) && $goods['limit_type'] == 2) {
                    return Normal::returnCode(Normal::FAIL, '限购数量为供应商限购，不可更改');
                }
            }
        }
        if (!isset($param['class_id']) || empty($param['class_id']) || (preg_match("/^[1-9]\d*$/", (string)$param['class_id']) != 1)) {
            return Normal::returnCode(Normal::FAIL, 'invalid argument class_id');
        }
        if (!isset($param['brand_id']) || empty($param['brand_id']) || (preg_match("/^[1-9]\d*$/", (string)$param['brand_id']) != 1)) {
            return Normal::returnCode(Normal::FAIL, 'invalid argument brand_id');
        }
        if (isset($param['warn_storage']) && $goods['warn_storage'] != $param['warn_storage']) {
            if (empty($param['warn_storage']) || (preg_match("/^[1-9]\d*$/", (string)$param['warn_storage']) != 1)) {
                return Normal::returnCode(Normal::FAIL, 'invalid argument warn_storage');
            }
        }
        if (isset($param['weight'])) {
            if ((preg_match("/^\d+(\.\d{0,4}+)?$/", (string)$param['weight']) != 1)) {
                return Normal::returnCode(Normal::FAIL, 'invalid argument weight');
            }
        }
        if (!isset($param['template_id']) || empty($param['template_id'])) {
            return Normal::returnCode(Normal::FAIL, 'invalid argument template_id');
        }
        if (isset($param['manager_tag']) && !empty($param['manager_tag'])) {
            if (!is_array($param['manager_tag'])) {
                return Normal::returnCode(Normal::FAIL, 'invalid argument manager_tag');
            }
        }
        if (isset($param['service_id']) && !empty($param['service_id'])) {
            if (empty($param['service_id']) || !is_array($param['service_id'])) {
                return Normal::returnCode(Normal::FAIL, 'invalid argument service_id');
            }
        }
        if (isset($param['show_order']) && $goods['show_order'] != $param['show_order']) {
            if (empty($param['show_order']) || (preg_match("/^[1-9]\d*$/", (string)$param['show_order']) != 1)) {
                return Normal::returnCode(Normal::FAIL, 'invalid argument show_order');
            }
        }
        if (!isset($param['spec_list']) || empty($param['spec_list']) || !is_array($param['spec_list'])) {
            return Normal::returnCode(Normal::FAIL, 'invalid argument spec_list');
        } else {
            $hasBatch      = GoodsBatch::where('goods_id', $param['goods_id'])->where('type', 0)->first();
            $hasBatch      = empty($hasBatch) ? [] : $hasBatch->toArray();
            $specList      = isset($hasBatch['spec_list']) && !empty($hasBatch['spec_list']) ? json_decode($hasBatch['spec_list'], true) : [['spec_num' => 1]];
            $specListByNum = array_column($specList, null, 'spec_num');
            $reqSpecNum    = array_column($param['spec_list'], 'spec_num');
            foreach ($param['spec_list'] as &$spec) {
                if (!isset($specListByNum[$spec['spec_num']])) {
                    return Normal::returnCode(Normal::FAIL, "规格{$spec['spec_num']}不存在");
                }
                if (!isset($spec['price_store']) || empty($spec['price_store']) || (preg_match("/^\d+(\.\d{0,2}+)?$/", (string)$spec['price_store']) != 1)) {
                    return Normal::returnCode(Normal::FAIL, "规格{$spec['spec_num']}结算价错误");
                }
                if (!isset($spec['price_recommend']) || empty($spec['price_recommend']) || (preg_match("/^\d+(\.\d{0,2}+)?$/", (string)$spec['price_recommend']) != 1)) {
                    return Normal::returnCode(Normal::FAIL, "规格{$spec['spec_num']}推荐零售价错误");
                }
                if (!isset($spec['price_recommend_vip']) || empty($spec['price_recommend_vip']) || (preg_match("/^\d+(\.\d{0,2}+)?$/", (string)$spec['price_recommend_vip']) != 1)) {
                    return Normal::returnCode(Normal::FAIL, "规格{$spec['spec_num']}推荐会员价错误");
                }
                if (isset($spec['price_market'])) {
                    if (preg_match("/^\d+(\.\d{0,2}+)?$/", (string)$spec['price_market']) != 1) {
                        return Normal::returnCode(Normal::FAIL, "规格{$spec['spec_num']}市场价错误");
                    }
                } else {
                    $spec['price_market'] = bcadd((string)$spec['price_recommend'], '10', 2);
                }
                //市场价设定值>推荐零售价设定值>推荐会员价设定值>结算价设定值
                if ($spec['price_market'] < $spec['price_recommend']) {
                    return Normal::returnCode(Normal::FAIL, "规格{$spec['spec_num']}市场价设定值需大于推荐零售价设定值");
                }
                if ($spec['price_recommend'] < $spec['price_recommend_vip']) {
                    return Normal::returnCode(Normal::FAIL, "规格{$spec['spec_num']}推荐零售价设定值大于推荐会员价设定值");
                }
                if ($spec['price_recommend_vip'] < $spec['price_store']) {
                    return Normal::returnCode(Normal::FAIL, "规格{$spec['spec_num']}推荐会员价设定值大于结算价设定值");
                }
            }
            unset($spec);
        }
        $saveData = [
            'name'        => $param['name'],
            'class_id'    => $param['class_id'],
            'brand_id'    => $param['brand_id'],
            'template_id' => $param['template_id'],
            'md'          => time(),
        ];
        if (isset($param['origin_id']) && $goods['origin_id'] != $param['origin_id']) {
            $origin = Country::where('id', $param['origin_id'])->where('df', 0)->value('name');
            if (!$origin) {
                return Normal::returnCode(Normal::FAIL, '国家不存在');
            }
            $saveData['origin_id'] = $param['origin_id'];
            $saveData['origin']    = $origin;
        }
        if (isset($param['buy_limit']) && $goods['buy_limit'] != $param['buy_limit']) {
            $saveData['buy_limit'] = $param['buy_limit'];
        }
        if (isset($param['show_order']) && $goods['show_order'] != $param['show_order']) {
            $saveData['show_order'] = $param['show_order'];
        }
        if (isset($param['warn_storage']) && $goods['warn_storage'] != $param['warn_storage']) {
            $saveData['warn_storage'] = $param['warn_storage'];
        }
        if (isset($param['weight'])) {
            $saveData['weight'] = !empty($param['weight']) ? bcdiv((string)$param['weight'], '1000', 4) : 0;;
        }
        if (isset($param['manager_tag']) && !empty($param['manager_tag'])) {
            $saveData['manager_tag'] = implode(',', $param['manager_tag']);
        }
        if (isset($param['service_id']) && !empty($param['service_id'])) {
            $saveData['service_id'] = implode(',', $param['service_id']);
        }
        $hasBatch         = GoodsBatch::where('goods_id', $param['goods_id'])->where('type', 0)->first();
        $hasBatch         = empty($hasBatch) ? [] : $hasBatch->toArray();
        $specList         = isset($hasBatch['spec_list']) && !empty($hasBatch['spec_list']) ? json_decode($hasBatch['spec_list'], true) : [['spec_num' => 1]];
        $specListByNum    = array_column($specList, null, 'spec_num');
        $specListPriceAll = GoodsSpecPrice::where('goods_id', $param['goods_id'])->get()->toArray();
        $specListPriceAll = array_column($specListPriceAll, null, 'spec_num');
        $reqSpecNum       = array_column($param['spec_list'], 'spec_num');
        if (count($reqSpecNum) != count($specListPriceAll)) {
            return Normal::returnCode(Normal::FAIL, "编辑的规格组数和现有的规格组数不相等");
        }
        $minSpecNum    = min($reqSpecNum);
        $is_high_goods = 0;
        Db::beginTransaction();
        try {
            foreach ($param['spec_list'] as $spec) {
                $specListPrice = $specListPriceAll[$spec['spec_num']] ?? [];
                if (!$specListPrice) {
                    throw new \RuntimeException("规格{$spec['spec_num']}的规格价格不存在");
                }
                foreach ($specList as $k1 => $v1) {
                    if ($v1['spec_num'] == $spec['spec_num']) {
                        $specList[$k1]['priceMarket'] = $spec['price_market'];
                    }
                }
                $price_cost = $specListPrice['price_cost']; //成本价
                if ($spec['price_store'] < $price_cost && $goods['medicinal'] == 0) {
                    throw new \RuntimeException("规格{$spec['spec_num']}的结算价不能小于成本价");
                }
                if ($goods['medicinal'] == 2) {
                    if (($specListPrice['price_cost'] != $price_cost) || ($specListPrice['price_recommend'] != $spec['price_recommend']) || ($specListPrice['price_recommend_vip'] != $spec['price_recommend_vip'])) {
                        throw new \RuntimeException("控价商品不支持改价");
                    }
                }
                if ($goods['medicinal'] == 1) {
                    if (($specListPrice['price_cost'] != $price_cost) || ($specListPrice['price_recommend'] > $spec['price_recommend']) || ($specListPrice['price_recommend_vip'] > $spec['price_recommend_vip'])) {
                        throw new \RuntimeException("规格{$spec['spec_num']}的限价商品价格必须大于推荐价格");
                    }
                }
                if ($goods['is_bonded'] == 1 && $goods['high_price'] > 0 && ($spec['price_recommend'] >= $goods['high_price'] * $spec['spec_num'] || $spec['price_recommend_vip'] >= $goods['high_price'] * $spec['spec_num'] || $spec['price_store'] >= $goods['high_price'] * $spec['spec_num'])) {
                    $is_high_goods = 1;
                }
                //查询预估利润是否为负
                if ($goods['is_bonded'] == 1 && $goods['high_price'] > 0) {
                    $pricestoretax_rate = $goods['tax_rate'];
                    $pricecosttax_rate  = $goods['tax_rate'];
                    if ($spec['price_store'] >= $goods['high_price']) {
                        $pricestoretax_rate = $goods['high_tax_rate'];
                    }
                    if ($price_cost >= $goods['high_price']) {
                        $pricecosttax_rate = $goods['high_tax_rate'];
                    }
                    $except_money = round(($spec['price_store'] / (1 + $pricestoretax_rate) - $price_cost / (1 + $pricecosttax_rate)), 2);
                    if ($except_money < 0) {
                        throw new \RuntimeException("规格{$spec['spec_num']}的修改价格失败，渠道利润为负");
                    }
                }
                $specPriceData = [
                    'price_market'        => $spec['price_market'], 'price_recommend' => $spec['price_recommend'],
                    'price_recommend_vip' => $spec['price_recommend_vip'], 'price_store' => $spec['price_store']
                ];
                GoodsSpecPrice::where('id', $specListPrice['id'])->update($specPriceData);
                //第一个规格，修改goods表价格
                if ($minSpecNum == $spec['spec_num']) {
                    $saveData['price_store']         = $spec['price_store'];
                    $saveData['price_recommend_vip'] = $spec['price_recommend_vip'];
                    $saveData['price_recommend']     = $spec['price_recommend'];
                    $saveData['price_market']        = $spec['price_market'];
                    if ($spec['price_store'] != $goods['price_store'] || ($goods['price_recommend'] != $spec['price_recommend']) || ($goods['price_recommend_vip'] != $spec['price_recommend_vip'])) {
                        $saveData['type']      = 2;
                        $saveData['is_update'] = 0;
                    }
                    $saveData['is_high_goods'] = $is_high_goods;
                }
            }
            Goods::where('id', $param['goods_id'])->where('cid', $param['cid'])->update($saveData);
            GoodsBatch::where('goods_id', $param['goods_id'])->where('type', 0)->update(['spec_list' => json_encode($specList)]);
            Db::commit();
        } catch (\Throwable $th) {
            Db::rollBack();
            return Normal::returnCode(Normal::FAIL, $th->getMessage());
        }
        if ($goods['status'] == 1) {
            $mnuser          = Mnuser::where('pid', $param['cid'])->where('auto_up', 1)->select(['id', 'mid', 'sid'])->get()->toArray();
            $mn_sids         = array_column($mnuser, 'id');
            $allMnStoreGoods = [];
            if ($mn_sids) {
                $allMnStoreGoods = MnStoreGoods::where('goods_id', $param['goods_id'])->whereIn('mn_sid', $mn_sids)->select(['id', 'goods_id', 'mn_sid'])->get()->toArray();
                $allMnStoreGoods = array_column($allMnStoreGoods, null, 'mn_sid');
            }
            $insert = [];
            foreach ($mnuser as $v) {
                $has = $allMnStoreGoods[$v['id']] ?? [];
                if (empty($has)) {
                    $item                  = [];
                    $item['mn_sid']        = $v['id'];
                    $item['mid']           = $v['mid'];
                    $item['sid']           = $v['sid'];
                    $item['goods_id']      = $param['goods_id'];
                    $item['status']        = 1;
                    $item['type']          = 2;
                    $item['cd']            = time();
                    $item['md']            = time();
                    $item['is_high_goods'] = $is_high_goods;
                    $item['price']         = $saveData['price_recommend'];
                    $item['price_vip']     = $saveData['price_recommend_vip'];
                    $insert[]              = $item;
                }
            }
            if (!empty($insert)) {
                MnStoreGoods::insert($insert);
            }
        }
        if ($goods['is_trade'] == 1) {
            CashGoodsChange::insert(['cid' => $param['cid'], 'mn_sid' => 0, 'goods_id' => $param['goods_id'], 'cd' => time()]);
        }

        if ($param['name'] != $goods['name'] || $param['class_id'] != $goods['class_id'] || $param['brand_id'] != $goods['brand_id']) {
            //ES更新索引
            ChannelCommodityEsService::instance()->updateIndexBySingleGoods($param['goods_id'], $param['cid']);
        }
        $goodsLogData = [
            'manager_id'   => $param['manager_id'],
            'manager_name' => $param['manager_name'],
            'common_id'    => $param['goods_id'],
            'old'          => json_encode($goods, 320),
            'info'         => json_encode($saveData, 320),
            'ip'           => $param['ip'],
            'cd'           => time(),
            'sid'          => getSID()
        ];
        GoodsLog::insert($goodsLogData);
        //更新店铺价格
        if ($saveData['price_store'] != $goods['price_store'] || $saveData['price_recommend_vip'] != $goods['price_recommend_vip'] || $saveData['price_recommend'] != $goods['price_recommend']) {
            $storeListFileds = ['mg.id', 'mg.type', 'mg.profit', 'mg.profit_vip', 'u.price_limit', 'mg.price', 'mg.price_vip', 'u.level'];
            $storeList       = MnStoreGoods::query()->from((new MnStoreGoods)->getTable() . ' as mg')->leftJoin('ly_mn_user as u', 'mg.mn_sid', '=', 'u.id')
                ->where('mg.goods_id', $param['goods_id'])->select($storeListFileds)->get()->toArray();
            if (!empty($storeList)) {
                foreach ($storeList as $k => $v) {
                    $price_store_cost = $saveData['price_store'];
                    $levelPrice       = $post_data['distributor_price'][$goods['base_spec']][$v['level']] ?? 0;
                    if (!empty($levelPrice)) {
                        $price_store_cost = $levelPrice;
                    }
                    switch ($v['type']) {
                        case 0:
                            $storeList[$k]['price']     = $price_store_cost + $v['profit'];
                            $storeList[$k]['price_vip'] = $price_store_cost + $v['profit_vip'];
                            break;
                        case 1:
                            $storeList[$k]['price']     = $price_store_cost + $price_store_cost * $v['profit'] / 100;
                            $storeList[$k]['price_vip'] = $price_store_cost + $price_store_cost * $v['profit_vip'] / 100;
                            break;
                        case 2:
                        default:
                            $storeList[$k]['price']     = $saveData['price_recommend'];
                            $storeList[$k]['price_vip'] = $saveData['price_recommend_vip'];
                            break;
                        case 3:
                            $storeList[$k]['price']     = $v['price'];
                            $storeList[$k]['price_vip'] = $v['price_vip'];
                            break;
                    }
                    $storeList[$k]['is_high_goods'] = 0;
                    if ($v['price_limit'] == 1 && $storeList[$k]['price_vip'] < $saveData['price_recommend_vip']) {
                        $storeList[$k]['price']     = $saveData['price_recommend'];
                        $storeList[$k]['price_vip'] = $saveData['price_recommend_vip'];
                        $storeList[$k]['type']      = 2;
                    }
                    $storeList[$k]['md'] = time();
                    if ($goods['is_bonded'] == 1 && $goods['tax_free'] == 0) {
                        $storeList[$k]['price']     = ($storeList[$k]['price'] * (1 + $goods['tax_rate'])) / $goods['base_spec'];
                        $storeList[$k]['price_vip'] = ($storeList[$k]['price_vip'] * (1 + $goods['tax_rate'])) / $goods['base_spec'];
                    } else {
                        $storeList[$k]['price']     = $storeList[$k]['price'] / $goods['base_spec'];
                        $storeList[$k]['price_vip'] = $storeList[$k]['price_vip'] / $goods['base_spec'];
                    }
                    if ($goods['is_bonded'] == 1 && $goods['high_price'] > 0 && ($storeList[$k]['price'] >= $goods['high_price'] || $storeList[$k]['price_vip'] >= $goods['high_price'])) {
                        $storeList[$k]['is_high_goods'] = 1;
                    }
                }
                //批量
                $updateSqlColumns = [
                    "type", "profit", "profit_vip", "price", "price_vip", "is_high_goods", "md"
                ];
                $when             = [];
                foreach ($storeList as $v1) {
                    foreach ($updateSqlColumns as $column) {
                        $then            = $v1[$column];
                        $when[$column][] = "WHEN {$v1['id']} THEN '{$then}'";
                    }
                }
                $updateSql = [];
                foreach ($updateSqlColumns as $column) {
                    $updateSql[] = "{$column} = CASE id " . (implode(" ", $when[$column])) . " END";
                }
                $updateSqlStr  = implode(",", $updateSql);
                $whereIds      = implode(",", array_column($storeList, 'id'));
                $databaseName  = MnStoreGoods::instance()->getConnection()->getDatabaseName();
                $tableName     = MnStoreGoods::instance()->getTable();
                $sql_batch_sql = "UPDATE `{$databaseName}`.`{$tableName}` SET {$updateSqlStr} WHERE ID IN({$whereIds})";
                Db::connection('bbc_commodity')->update($sql_batch_sql);
            }
        }
        return Normal::returnCode(Normal::SUC, '修改成功');
    }

    /**
     * 代发商品修改价格模板
     * @param array $param
     */
    public function excelPriceEditTpl(array $param) {
        $param['sp'] = 0;
        $whereRaw    = ChannelCommodityCommonService::instance()->handleWhere($param);
        $sortRaw     = ChannelCommodityCommonService::instance()->handleSort($param);
        $fields      = ['id', 'skucode', 'price_cost', 'price_market', 'price_vip', 'price_store', 'price_recommend', 'price_recommend_vip', 'name', 'barcode', 'is_trade',];
        $list        = Goods::select($fields)->where('is_trade', 0)->whereRaw($whereRaw)->orderByRaw($sortRaw)->get()->toArray();
        $excelTitle  = ['sku', '规格数量', '下游结算价', '推荐会员价', '推荐零售价', '市场价(非必填)', '成本价', '名称', '国际编码'];
        if (!$list) {
            $exportRes = ExportExcelHandle::instance()->uploadAliOssSource('价格导入模板.xlsx', $excelTitle, []);
            if ($exportRes['code'] != Normal::SUC) {
                return Normal::returnCode(Normal::FAIL, $exportRes['msg'] ?? '生成价格模板失败');
            }
            return Normal::returnCode(Normal::SUC, "生成价格模板成功", ['download_url' => $exportRes['data']['path'],]);
        }
        $distributor_level       = DistributorLevel::where('cid', $param['cid'])->orderBy('level', 'asc')->select(['level', 'name'])->get()->toArray();
        $distributor_level_index = array_column($distributor_level, 'name', 'level');
        $goods_ids               = array_column($list, 'id');
        $goodsSpec               = GoodsSpecPrice::whereIn('goods_id', $goods_ids)->orderBy('spec_num', 'asc')->get()->toArray();
        $specBygid               = [];
        if ($goodsSpec) {
            foreach ($goodsSpec as $spec) {
                $specBygid[$spec['goods_id']][] = $spec;
            }
        }
        $hasBatchAll                = GoodsBatch::whereIn('goods_id', $goods_ids)->where('df', 0)->where('type', 0)->get()->toArray();
        $hasBatchAll                = $hasBatchAll ? array_column($hasBatchAll, null, 'goods_id') : [];
        $distributor_level_pric_arr = DistributorPrice::where('cid', $param['cid'])->whereIn('goods_id', $goods_ids)->select(['goods_id', 'price', 'level_id', 'spec_num'])->get();
        $excelData                  = [];
        foreach ($list as $k => $v) {
            $excelData[$k]['skucode'] = $v['skucode'];
            $specList                 = $specBygid[$v['id']] ?? [];
            if (!empty($specList)) {
                $specList            = collect($specList)->sortBy('spec_num')->toArray();
                $specList            = array_column($specList, null, 'spec_num');
                $specNum             = array_column($specList, 'spec_num');
                $spec                = '';
                $price_store         = '';
                $price_recommend_vip = '';
                $price_recommend     = '';
                $price_market        = '';
                $price_cost          = '';
                foreach ($specNum as $item) {
                    $spec                .= $item . ',';
                    $price_store         .= $specList[$item]['price_store'] . ',';
                    $price_recommend_vip .= $specList[$item]['price_recommend_vip'] . ',';
                    $price_recommend     .= $specList[$item]['price_recommend'] . ',';
                    $price_market        .= $specList[$item]['price_market'] . ',';
                    $price_cost          .= $specList[$item]['price_cost'] . ',';
                }
                $excelData[$k]['spec']                = rtrim($spec, ',');
                $excelData[$k]['price_store']         = rtrim($price_store, ',');
                $excelData[$k]['price_recommend_vip'] = rtrim($price_recommend_vip, ',');
                $excelData[$k]['price_recommend']     = rtrim($price_recommend, ',');
                $excelData[$k]['price_market']        = rtrim($price_market, ',');
                $excelData[$k]['price_cost']          = rtrim($price_cost, ',');
            } else {
                if ($v['is_trade'] == 1) {
                    $excelData[$k]['spec'] = 1;
                } else {
                    $has_batch = $hasBatchAll[$v['id']] ?? [];
                    $spec_list = isset($has_batch['spec_list']) && !empty($has_batch['spec_list']) ? json_decode($has_batch['spec_list'], true) : '';
                    $baseSpec  = 1;
                    if (!empty($spec_list)) {
                        $baseSpec = $spec_list[0]['spec_num'] ?? 1;
                    }
                    $excelData[$k]['spec'] = $baseSpec;
                }
                $excelData[$k]['price_store']         = $v['price_store'];
                $excelData[$k]['price_recommend_vip'] = $v['price_recommend_vip'];
                $excelData[$k]['price_recommend']     = $v['price_recommend'];
                $excelData[$k]['price_market']        = $v['price_market'];
                $excelData[$k]['price_cost']          = $v['price_cost'];
            }
            $excelData[$k]['name']    = $v['name'];
            $excelData[$k]['barcode'] = $v['barcode'];
            $distributor_level_price  = $distributor_level_pric_arr->where('goods_id', $v['id'])->toArray();;
            $distributor_level_pric_index = array_column($distributor_level_price, null, 'level_id');
            $new_spec_level_price         = [];
            foreach ($distributor_level_price as $val) {
                $new_spec_level_price[$val['level_id']][$val['spec_num']] = $val['price'];
            }
            foreach ($distributor_level_index as $key => $val) {
                if (!empty($specList)) {
                    $specLevel = '';
                    foreach ($specNum as $item) {
                        $price     = $new_spec_level_price[$key][$item] ?? $specList[$item]['price_store'];
                        $specLevel .= $price . ',';
                    }
                    $excelData[$k][] = rtrim($specLevel, ',');
                } else {
                    if (array_key_exists($key, $new_spec_level_price)) { //设置了等级分销商结算价
                        $excelData[$k][] = $distributor_level_pric_index[$key]['price'];
                    } else {
                        $excelData[$k][] = $v['price_store'];
                    }
                }
            }
        }
        foreach ($distributor_level_index as $v) {
            $excelTitle[] = $v;
        }
        $exportRes = ExportExcelHandle::instance()->uploadAliOssSource('价格导入模板.xlsx', $excelTitle, $excelData);
        if ($exportRes['code'] != Normal::SUC) {
            return Normal::returnCode(Normal::FAIL, $exportRes['msg'] ?? '生成价格模板失败');
        }
        return Normal::returnCode(Normal::SUC, "生成价格模板成功", ['download_url' => $exportRes['data']['path'],]);
    }

    /**
     * 代发商品修改商品资料模板
     * @param array $param
     */
    public function excelDetailEditTpl(array $param) {
        $param['sp'] = 0;
        $whereRaw    = ChannelCommodityCommonService::instance()->handleWhere($param);
        $sortRaw     = ChannelCommodityCommonService::instance()->handleSort($param);
        $fields      = ['id', 'skucode', 'class_id', 'name', 'brand_id', 'show_order'];
        $list        = Goods::select($fields)->where('is_trade', 0)->whereRaw($whereRaw)->orderByRaw($sortRaw)->get()->toArray();
        $excelTitle  = ['sku', '商品名称', '商品分类', '品牌', 'b2b排序值（非必填）'];
        if (!$list) {
            $exportRes = ExportExcelHandle::instance()->uploadAliOssSource('修改代发商品资料模板.xlsx', $excelTitle, []);
            if ($exportRes['code'] != Normal::SUC) {
                return Normal::returnCode(Normal::FAIL, $exportRes['msg'] ?? '生成修改代发商品资料模板失败');
            }
            return Normal::returnCode(Normal::SUC, "生成修改代发商品资料模板成功", ['download_url' => $exportRes['data']['path'],]);
        }
        $class_ids  = array_column($list, 'class_id');
        $classIndex = GoodsClass::whereIn('id', $class_ids)->pluck('name', 'id')->toArray();
        $brand_ids  = array_column($list, 'brand_id');
        $brandIndex = GoodsBrand::whereIn('id', $brand_ids)->pluck('name', 'id')->toArray();
        $excelData  = [];
        foreach ($list as $k => $v) {
            $excelData[$k]['skucode'] = $v['skucode'];
            $excelData[$k]['name']    = $v['name'];
            if ($v['class_id'] == 0) {
                $excelData[$k]['class_name'] = '无分类';
            } else {
                $excelData[$k]['class_name'] = $classIndex[$v['class_id']] ?? '无分类';
            }
            $excelData[$k]['brand_name'] = $brandIndex[$v['brand_id']] ?? '';
            $excelData[$k]['show_order'] = $v['show_order'];
        }
        $exportRes = ExportExcelHandle::instance()->uploadAliOssSource('修改代发商品资料模板.xlsx', $excelTitle, $excelData);
        if ($exportRes['code'] != Normal::SUC) {
            return Normal::returnCode(Normal::FAIL, $exportRes['msg'] ?? '生成修改代发商品资料模板失败');
        }
        return Normal::returnCode(Normal::SUC, "生成修改代发商品资料模板成功", ['download_url' => $exportRes['data']['path'],]);
    }

    /**
     * 云仓推送的商品成本价变更提示设置
     * 1单条不再提示 2全部不再提示
     * @param array $param
     */
    public function setPriceCostChange(array $param) {
        if (!isset($param['cid']) || empty($param['cid']) || (preg_match("/^[1-9]\d*$/", (string)$param['cid']) != 1)) {
            return Normal::returnCode(Normal::FAIL, 'invalid argument cid');
        }
        if (!isset($param['show_status']) || !in_array($param['show_status'], ['1', '2'])) {
            return Normal::returnCode(Normal::FAIL, 'invalid argument show_status');
        }
        if ($param['show_status'] == 1) {
            if (!isset($param['goods_id']) || empty($param['goods_id']) || (preg_match("/^[1-9]\d*$/", (string)$param['goods_id']) != 1)) {
                return Normal::returnCode(Normal::FAIL, 'invalid argument goods_id');
            }
        }
        $param['cid'] = (int)($param['cid']);
        $model        = Goods::where('cid', $param['cid'])->where('is_price_cost_change', 1);
        $data         = ['md' => time(), 'is_price_cost_change' => 0];
        if ($param['show_status'] == 1) {
            $model = $model->where('id', $param['goods_id']);
        }
        $model->update($data);
        return Normal::returnCode(Normal::SUC, '设置成功');
    }

    /**
     * 商品扩展信息
     * 部分 商品基础信息、价格信息
     * @param array $param
     */
    public function goodsExtInfo(array $param) {
        if (!isset($param['cid']) || empty($param['cid']) || (preg_match("/^[1-9]\d*$/", (string)$param['cid']) != 1)) {
            return Normal::returnCode(Normal::FAIL, 'invalid argument cid');
        }
        if (!isset($param['goods_id']) || empty($param['goods_id']) || (preg_match("/^[1-9]\d*$/", (string)$param['goods_id']) != 1)) {
            return Normal::returnCode(Normal::FAIL, 'invalid argument goods_id');
        }
        $fields = [
            'id', 'name', 'skucode', 'weight', 'type', 'is_bonded', 'supply_class_id',
            'manager_tag', 'service_id', 'warn_storage', 'buy_limit', 'show_order', 'tax_free',
            'high_price', 'tax_rate', 'high_tax_rate', 'price_store', 'price_recommend', 'price_recommend_vip',
            'price_market', 'is_update', 'template_id',
        ];
        $info   = Goods::select($fields)->where('id', $param['goods_id'])->where('cid', $param['cid'])->first();
        if (empty($info)) {
            return Normal::returnCode(Normal::FAIL, "指定商品信息不存在");
        }
        $info                      = $info->toArray();
        $info['weight_kg']         = round($info['weight'] / 1000, 3);
        $info['settlement_type']   = Goods::$settlementType[$info['type']] ?? '未定义';
        $info['goods_type']        = Goodscommon::$is_bonded[$info['is_bonded']] ?? '';
        $info['supply_class_text'] = GoodsSupplyClass::where('id', $info['supply_class_id'])->value('name');
        $tagArr                    = GoodsManagerTags::where('cid', $param['cid'])->where('df', 0)->pluck('name', 'id')->toArray();
        $info['manager_tag_text']  = '';
        if (!empty($info['manager_tag'])) {
            $managerTagArr     = explode(',', $info['manager_tag']);
            $managerTagTextArr = [];
            foreach ($managerTagArr as $v6) {
                $str6 = $tagArr[$v6] ?? '未定义';
                array_push($managerTagTextArr, $str6);
            }
            if ($managerTagTextArr) {
                $info['manager_tag_text'] = implode(',', $managerTagTextArr);
            }
        }
        $serviceArr           = GoodsService::where('cid', $param['cid'])->where('status', 1)->pluck('title', 'id')->toArray();
        $info['service_text'] = '';
        if (!empty($info['service_id'])) {
            $service_ids    = explode(',', $info['service_id']);
            $serviceTextArr = [];
            foreach ($service_ids as $serid) {
                if (isset($serviceArr[$serid])) {
                    array_push($serviceTextArr, $serviceArr[$serid]);
                }
            }
            $info['service_text'] = $serviceTextArr ? implode(',', $serviceTextArr) : '';
        }
        $info['template'] = TransitTemplate::where('cid', $param['cid'])->where('id', $info['template_id'])->where('df', 0)->value('name');
        if ($info['buy_limit'] == 0 && $info['is_bonded'] == 1) {
            $info['buy_limit'] = 6;
        }
        if ($info['buy_limit'] == 0) {
            $info['buy_limit'] = '无';
        }
        $specArr = GoodsSpecPrice::where('goods_id', $info['id'])->get()->toArray();
        $payRate = ConfigChannel::instance()->getPayFee(['cid' => $param['cid']]);
        $newSpec = [];
        foreach ($specArr as $spec) {
            $costUnitPrice            = bcdiv((string)($spec['price_cost']), (string)($spec['spec_num']), 2);//成本单价
            $settlementUnitPrice      = bcdiv((string)($spec['price_store']), (string)($spec['spec_num']), 2);//结算单价
            $costUnitPricNoTax        = $costUnitPrice;//不含税成本单价
            $settlementUnitPriceNoTax = $settlementUnitPrice;//不含税结算单价
            if ($info['is_bonded'] == 1 && $info['tax_free'] == 1) {
                if ($info['high_price'] > 0) {
                    $pricestoretax_rate = $info['tax_rate'];
                    $pricecosttax_rate  = $info['tax_rate'];
                    if ($settlementUnitPrice >= $info['high_price']) {
                        $pricestoretax_rate = $info['high_tax_rate'];
                    }
                    if ($costUnitPrice >= $info['high_price']) {
                        $pricecosttax_rate = $info['high_tax_rate'];
                    }
                    $settlementUnitPriceNoTax = round(($settlementUnitPrice / (1 + $pricestoretax_rate)), 2);
                    $costUnitPricNoTax        = round($costUnitPrice / (1 + $pricecosttax_rate), 2);
                } else {
                    $settlementUnitPriceNoTax = round($settlementUnitPrice / (1 + $info['tax_rate']), 2);
                    $costUnitPricNoTax        = round($costUnitPrice / (1 + $info['tax_rate']), 2);
                }
            }
            $unitProfit      = bcsub((string)$settlementUnitPriceNoTax, (string)$costUnitPricNoTax, 2);
            $unitProfitTotal = bcmul($unitProfit, (string)($spec['spec_num']), 2);
            $newSpec[]       = [
                'spec_num'               => $spec['spec_num'],
                'price_market'           => $spec['price_market'],
                'price_recommend'        => $spec['price_recommend'],
                'price_recommend_vip'    => $spec['price_recommend_vip'],
                'high_price'             => bcmul((string)($spec['spec_num']), (string)($info['high_price']), 2),//含税预警价
                'cost_price_total'       => $costUnitPrice . '/' . $spec['price_cost'],
                'settlement_price_total' => $settlementUnitPrice . '/' . $spec['price_store'],
                'unit_profit_total'      => round($unitProfit * $payRate, 2) . '/' . round($unitProfitTotal * $payRate, 2),//单件利润小计算
            ];
        }
        $info['goods_spec'] = $newSpec;
        return Normal::returnCode(Normal::SUC, '获取成功', $info);
    }

}
